using EmailContacts.ServiceInterface;
using Funq;
using ServiceStack;
using ServiceStack.Api.OpenApi;
using ServiceStack.MiniProfiler;
using System;
using System.Collections.Generic;
using System.Web.Routing;
using EmailContacts.ServiceModel;
using EmailContacts.ServiceModel.Types;
using Ninject;
using ServiceStack.Configuration;
using ServiceStack.Data;
using ServiceStack.Host;
using ServiceStack.Messaging;
using ServiceStack.MiniProfiler.Data;
using ServiceStack.OrmLite;
using ServiceStack.RabbitMq;
using ServiceStack.Razor;
using ServiceStack.Validation;

namespace EmailContacts
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            new AppHost().Init();
        }


        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            if (Request.IsLocal)
            {
                Profiler.Start(); 
            }
        }

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            Profiler.Stop();
        }
    }

    public sealed class AppHost : AppHostBase
    {
        public AppHost() : base("Email Contact Services", typeof(ContactsServices).Assembly)
        {
            // 动态添加路由
            typeof(GetStudent)
                .AddAttributes(new RouteAttribute("/students/{Id}", "GET"));
            typeof(FindStudents)
                .AddAttributes(new RouteAttribute("/students", "GET"));
        }

        public override void Configure(Container container)
        {
            Config.AppendUtf8CharsetOnContentTypes.Add("text/html");
            
            Plugins.Add(new OpenApiFeature());
            Plugins.Add(new RazorFormat());
            Plugins.Add(new RequestLogsFeature());
            
            Plugins.Add(new MiniProfilerFeature());
            Plugins.Add(new PostmanFeature());
            Plugins.Add(new CorsFeature());
            
            Plugins.Add(new AutoQueryFeature());
            
            Plugins.Add(new ValidationFeature());
            container.RegisterValidators(typeof(ContactsServices).Assembly);

            container.Register<IDbConnectionFactory>(c=>new OrmLiteConnectionFactory(
                    "~/db.sqlite".MapHostAbsolutePath(), SqliteDialect.Provider
                )
            {
                ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current)
            }).InitializedBy((container1, factory) =>
            {
                using (var db = factory.Open())
                {
                    db.DropAndCreateTables(typeof(Email), typeof(Contact), typeof(Student));
                    
                    ContactsServices.AddContacts(db);
                    StudentsService.AddStudents(db);
                }
            });

//            UseDbEmailer(container);
            
            UseSmtpEmailer(container);
            
            ConfigureRabbitMqServer(container);
        }
        
        /// <summary>
        /// 配置 RabbitMq 服务器
        /// </summary>
        /// <param name="container"></param>
        private void ConfigureRabbitMqServer(Container container)
        {
            container.Register<IMessageService>(
                c => new RabbitMqServer(
                    new RabbitMqMessageFactory{
                        ConnectionFactory = {VirtualHost = "vsnet_mq", UserName = "admin", Password = "abc123"}
                    }
                )
            );

            var mqServer = container.Resolve<IMessageService>();
            
            mqServer.RegisterHandler<EmailContact>(ServiceController.ExecuteMessage);
            
            mqServer.Start();
        }
        
        /// <summary>
        /// 使用数据库邮件发送器
        /// </summary>
        /// <param name="container"></param>
        private static void UseDbEmailer(Container container)
        {
            container.RegisterAs<DbEmailer, IEmailer>()
                .ReusedWithin(ReuseScope.Request);
        }
        
        /// <summary>
        /// 使用 Smtp 邮件发送器
        /// </summary>
        /// <param name="container"></param>
        private static void UseSmtpEmailer(Container container)
        {
            var appSettings = new AppSettings();

            container.Register(appSettings.Get("SmtpConfig"), new SmtpConfig
            {
                Host = "smtp.126.com",
                Port = 465,
                UserName = "daves2009@126.com",
                Password = "lilanjun1989"
            });

            container.RegisterAs<SmtpEmailer, IEmailer>()
                .ReusedWithin(ReuseScope.Request);
        }

        public override void Release(object instance)
        {
            base.Release(instance);
        }
    }
}